﻿using BCCommon;
using BCData.Sim.Admin.AdminPermissionMappingPage;
using BCData.Sim.Admin.AdminPermissionRecord;
using BCData.Sim.Admin.StaffOrganizationMappingRecord;
using BCDto.Sim.Admin.AdminPermissionMappingPage;
using BCEntity.Common.EntityNameConst;
using BCEntity.Sim.Admin.AdminPermissionMappingPage;
using BCService.Utils;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;

namespace BCService.Sim.Admin.AdminPermissionMappingPage
{
    public class AdminPermissionMappingPageService : IAdminPermissionMappingPageService
    {
        private readonly IAdminPermissionMappingPageData adminPermissionMappingPageData;
        private readonly IAdminPermissionRecordData adminPermissionRecordData;
        private readonly IStaffOrganizationMappingRecordData staffOrganizationMappingRecordData;
        private readonly IRedisService redisService;
        private readonly string key = string.Format("{0}", EntityNameConst.AdminPermissionMappingPageViewDto);
        private readonly string departmentKey = string.Format("{0}", EntityNameConst.DepartmentPermissionListEntity);

        public AdminPermissionMappingPageService(IAdminPermissionMappingPageData adminPermissionMappingPageData,
            IAdminPermissionRecordData adminPermissionRecordData,
            IStaffOrganizationMappingRecordData staffOrganizationMappingRecordData,
            IRedisService redisService)
        {
            this.adminPermissionMappingPageData = adminPermissionMappingPageData;
            this.adminPermissionRecordData = adminPermissionRecordData;
            this.staffOrganizationMappingRecordData = staffOrganizationMappingRecordData;
            this.redisService = redisService;
        }

        public AdminPermissionMappingPageDto Add(AdminPermissionMappingPageRequestDto requestDto)
        {
            if (string.IsNullOrWhiteSpace(requestDto.PagePathCode.Trim()))
            {
                throw new ArgumentException("此页面路径码为必填项");
            }
            if (string.IsNullOrWhiteSpace(requestDto.PermissionCode.Trim()))
            {
                throw new ArgumentException("此权限码为必填项");
            }
            if (this.adminPermissionMappingPageData.CheckExists(requestDto.PagePathCode).GetAwaiter().GetResult())
            {
                throw new ArgumentException("此页面路径码已存在");
            }
            if (this.adminPermissionMappingPageData.CheckPermissionCodeExists(requestDto.PermissionCode).GetAwaiter().GetResult())
            {
                throw new ArgumentException("此权限码已存在");
            }
            var entity = requestDto.As<AdminPermissionMappingPageEntity>();
            entity.PagePathHashCode = requestDto.PagePathCode.SHA1();
            entity.MappingHashCode = string.Concat(entity.PagePathHashCode, entity.PermissionCode).SHA1();
            entity.PagePathCode = requestDto.PagePathCode.TrimStart('/').TrimEnd('/');
            entity.PathLevel = requestDto.PagePathCode.TrimStart('/').TrimEnd('/').IndexOf("/") > 0 ? requestDto.PagePathCode.TrimStart('/').TrimEnd('/').Split("/").Length - 1 : 0;
            if (entity.PagePathCode.IndexOf("/") > -1)
            {
                entity.ParentPathCode = entity.PagePathCode.Substring(0, entity.PagePathCode.LastIndexOf("/"));
            }
            else
            {
                entity.ParentPathCode = null;
            }
            if (entity.PathLevel > 0 && entity.PathLevel < 3 && string.IsNullOrWhiteSpace(entity.Icon))
            {
                throw new ArgumentException("三级以下目录请填写图标标签名称");
            }

            if (string.IsNullOrWhiteSpace(entity.ParentPathCode))
            {
                var lastEntity = this.adminPermissionMappingPageData.GetLastRootEntity().GetAwaiter().GetResult();
                if (lastEntity != null)
                    entity.PageOrder = lastEntity.PageOrder + 1;
                else
                    entity.PageOrder = 1;
            }
            else
            {
                var lastEntity = this.adminPermissionMappingPageData.GetLastOrderEntityByParentPathCode(entity.ParentPathCode).GetAwaiter().GetResult();
                if (lastEntity != null)
                    entity.PageOrder = lastEntity.PageOrder + 1;
                else
                    entity.PageOrder = 1;
            }

            var result = this.adminPermissionMappingPageData.Add(entity).GetAwaiter().GetResult().As<AdminPermissionMappingPageDto>();
            if (result != null)
            {
                string adminRecordKey = string.Format("{0}", EntityNameConst.AdminPermissionRecordListEntity);
                this.redisService.DeleteMultipleKey(key, false);
                this.redisService.DeleteMultipleKey(adminRecordKey, false);
            }
            return result;
        }

        public bool CheckExists(string pagePathCode)
        {
            return this.adminPermissionMappingPageData.CheckExists(pagePathCode).GetAwaiter().GetResult();
        }

        public bool CheckPermissionCodeExists(string permissionCode)
        {
            return this.adminPermissionMappingPageData.CheckPermissionCodeExists(permissionCode).GetAwaiter().GetResult();
        }

        public void Delete(long adminPermissionMappingPageId)
        {
            var entity = this.adminPermissionMappingPageData.GetEntity(adminPermissionMappingPageId).GetAwaiter().GetResult();
            if (this.adminPermissionRecordData.CheckExists(entity.PermissionCode).GetAwaiter().GetResult())
            {
                throw new ArgumentException("此员工页面权限映射已被员工权限记录所使用，无法删除");
            }
            this.adminPermissionMappingPageData.Delete(adminPermissionMappingPageId);
            this.redisService.DeleteAsync(key);
        }

        public (IEnumerable<StaffRolePermissionPageRecordDto>, List<PageMenuDto>) GetAdminPagePermissions(long? adminId,long? staffOrganizationMappingRecordId)
        {
            string cacheKey = this.redisService.GetKey(key, adminId ?? 0, staffOrganizationMappingRecordId);
            var result = this.redisService.TryGet(cacheKey, () =>
            {
                var data = this.adminPermissionMappingPageData.GetListByAdminIdAsync(adminId).GetAwaiter().GetResult();
                return data;
            },TimeSpan.FromMinutes(30));

            List<StaffRolePermissionPageRecordEntity> list = new List<StaffRolePermissionPageRecordEntity>();
            if (adminId.HasValue&&staffOrganizationMappingRecordId.HasValue)
            {
                var staffOrganizationMappingRecordEntity = this.staffOrganizationMappingRecordData.GetEntity(staffOrganizationMappingRecordId.Value).GetAwaiter().GetResult();
                if (staffOrganizationMappingRecordEntity == null)
                {
                    throw new ArgumentException("此员工角色信息不存在");
                }
                result = result.Where(p => p.StaffOrganizationMappingRecordId == staffOrganizationMappingRecordEntity.StaffOrganizationMappingRecordId);
               
                var menu = result.OrderBy(p => p.PagePathCode);
                foreach (var item in menu)
                {
                    if (item.PathLevel == 0&&item.EnabledSelect)
                    {
                        list.Add(item);
                    }
                    else if(list.Any(p=>p.PagePathCode == item.ParentPathCode)&&item.EnabledSelect)
                    {
                        list.Add(item);
                    }
                }
            }
            else
            {
                foreach(var item in result)
                {
                    item.EnabledDelete = true;
                    item.EnabledInsert = true;
                    item.EnabledSelect = true;
                    item.EnabledUpdate = true;
                }
                list = result.ToList();
            }
            List<PageMenuDto> resultData = new List<PageMenuDto>();
            resultData.AddRange(list.Where(p => p.PathLevel == 0).OrderBy(p => p.PageOrder).As<List<PageMenuDto>>());
            GetChildrenPageMenu(list, resultData);
            return (list.As<IEnumerable<StaffRolePermissionPageRecordDto>>(), resultData);
        }

        private void GetChildrenPageMenu(IEnumerable<StaffRolePermissionPageRecordEntity> data, List<PageMenuDto> result)
        {
            foreach (var item in result)
            {
                var children = data.Where(p => p.ParentPathCode == item.Path.TrimStart('/') && p.PathLevel == item.Level + 1).OrderBy(p => p.PageOrder).As<List<PageMenuDto>>();
                if (children.Any())
                {
                    GetChildrenPageMenu(data, children);
                    item.Children = children;
                }
            }
        }

        public IEnumerable<AdminPermissionMappingPageViewDto> GetList(int? departmentId)
        {
            string cacheKey = this.redisService.GetKey(departmentKey, departmentId ?? new Nullable<int>());
            var result = this.redisService.TryGet(cacheKey, () =>
            {
                var data = this.GetAdminPermissionMappings(departmentId);
                return data;
            }, TimeSpan.FromMinutes(30));

            return result;
        }

        /// <summary>
        /// 从数据库中获取权限页面映射关系
        /// </summary>
        /// <returns></returns>
        private List<AdminPermissionMappingPageViewDto> GetAdminPermissionMappings(int? departmentId)
        {
            List<AdminPermissionMappingPageViewDto> list = this.adminPermissionMappingPageData.GetList(departmentId).GetAwaiter().GetResult().As<List<AdminPermissionMappingPageViewDto>>();
            foreach (var item in list)
            {
                item.Children = new List<OperationPermissionDto>()
                {
                    new OperationPermissionDto(){ Label = "查看", Value = item.PermissionCode+".Select" },
                    new OperationPermissionDto(){ Label = "添加", Value = item.PermissionCode+".Insert" },
                    new OperationPermissionDto(){ Label = "修改", Value = item.PermissionCode+".Update" },
                    new OperationPermissionDto(){ Label = "删除", Value = item.PermissionCode+".Delete" }
                };
            }
            return list;
        }

        public PageableList<AdminPermissionMappingPageDto> Query(string permissionCode, string parentPathCode, bool fixedParentPathCode, int? pathLevel, int pageIndex = 1, int pageSize = 10)
        {
            string cacheKey = this.redisService.GetKey(departmentKey, permissionCode, parentPathCode, fixedParentPathCode, pathLevel, pageIndex, pageSize);
            var result = this.redisService.TryGet(cacheKey, () =>
            {
                var data = this.adminPermissionMappingPageData.Query(permissionCode, parentPathCode, fixedParentPathCode, pathLevel, pageIndex, pageSize).GetAwaiter().GetResult();
                return new PageableList<AdminPermissionMappingPageDto>
                {
                    Items = data.Item1.As<IEnumerable<AdminPermissionMappingPageDto>>(),
                    Count = data.Item2,
                    ServerTime = DateTime.Now,
                    PageIndex = pageIndex,
                    PageSize = pageSize
                };
            }, TimeSpan.FromMinutes(30));
            return result;
        }

        public AdminPermissionMappingPageDto Update(AdminPermissionMappingPagePutDto putDto)
        {
            var mappingEntity = this.adminPermissionMappingPageData.GetEntity(putDto.AdminPermissionMappingPageId).GetAwaiter().GetResult();
            if (mappingEntity == null)
            {
                throw new ArgumentException("此页面权限映射信息不存在");
            }
            if (string.IsNullOrWhiteSpace(putDto.PagePathCode.Trim()))
            {
                throw new ArgumentException("此页面路径码为必填项");
            }
            if (string.IsNullOrWhiteSpace(putDto.PermissionCode.Trim()))
            {
                throw new ArgumentException("此权限码为必填项");
            }
            if (mappingEntity.PagePathCode != putDto.PagePathCode)
            {
                if (this.adminPermissionMappingPageData.CheckExists(putDto.PagePathCode).GetAwaiter().GetResult())
                {
                    throw new ArgumentException("此页面路径码已存在");
                }
            }
            if (mappingEntity.PermissionCode != putDto.PermissionCode)
            {
                if (this.adminPermissionMappingPageData.CheckPermissionCodeExists(putDto.PermissionCode).GetAwaiter().GetResult())
                {
                    throw new ArgumentException("此权限码已存在");
                }
            }
            var entity = putDto.As<AdminPermissionMappingPageEntity>();
            entity.PagePathHashCode = entity.PagePathCode.SHA1();
            entity.MappingHashCode = string.Concat(entity.PagePathHashCode, entity.PermissionCode).SHA1();
            entity.PagePathCode = putDto.PagePathCode.TrimStart('/').TrimEnd('/');
            entity.PathLevel = putDto.PagePathCode.TrimStart('/').TrimEnd('/').IndexOf("/") > 0 ? putDto.PagePathCode.TrimStart('/').TrimEnd('/').Split("/").Length - 1 : 0;
            if (entity.PagePathCode.IndexOf("/") > -1)
            {
                entity.ParentPathCode = entity.PagePathCode.Substring(0, entity.PagePathCode.LastIndexOf("/"));
            }
            else
            {
                entity.ParentPathCode = null;
            }
            if (entity.PathLevel > 0 && entity.PathLevel < 2 && string.IsNullOrWhiteSpace(entity.Icon))
            {
                throw new ArgumentException("三级以下目录请填写图标标签名称");
            }
            var result = this.adminPermissionMappingPageData.Update(entity).GetAwaiter().GetResult().As<AdminPermissionMappingPageDto>();
            if (result != null)
            {
                string adminRecordKey = string.Format("{0}", EntityNameConst.AdminPermissionRecordListEntity);
                this.redisService.DeleteMultipleKey(key, false);
                this.redisService.DeleteMultipleKey(adminRecordKey, false);
            }
            return result;
        }
        public void UpdatePageOrder(AdminPermissionMappingPageDto dto)
        {
            var entity = this.adminPermissionMappingPageData.GetEntity(dto.AdminPermissionMappingPageId).GetAwaiter().GetResult();
            if (entity == null)
            {
                throw new ArgumentException("页面不存在");
            }
            List<AdminPermissionMappingPageEntity> oldEntities = new List<AdminPermissionMappingPageEntity>();
            entity.PageOrder = dto.PageOrder;
            oldEntities.Add(entity);
            if (!this.adminPermissionMappingPageData.UpdatePageOrder(oldEntities).GetAwaiter().GetResult())
            {
                throw new ArgumentException("调整页面顺序失败");
            }
            string adminRecordKey = string.Format("{0}", EntityNameConst.AdminPermissionRecordListEntity);
            this.redisService.DeleteMultipleKey(key, false);
            this.redisService.DeleteMultipleKey(adminRecordKey, false);
        }

        public void UpdatePageOrder(IEnumerable<AdminPermissionMappingPageDto> dtos)
        {
            if (dtos.Count() > 2)
            {
                throw new ArgumentException("调整页面顺序仅支持两个页面调整，无法对多于两个页面的顺序进行调整");
            }
            List<AdminPermissionMappingPageEntity> oldEntities = new List<AdminPermissionMappingPageEntity>();
            foreach (var dto in dtos)
            {
                var entity = this.adminPermissionMappingPageData.GetEntity(dto.AdminPermissionMappingPageId).GetAwaiter().GetResult();
                if (entity == null)
                {
                    throw new ArgumentException("页面不存在");
                }
                oldEntities.Add(entity);
            }

            var oneEntity = oldEntities.ElementAt(0);
            var twoEntity = oldEntities.ElementAt(1);

            int oneOrder = oneEntity.PageOrder;
            int twoOrder = twoEntity.PageOrder;
            if (oneOrder == 0 && twoOrder == 0)
            {
                oneOrder = 1;
                twoOrder = 2;
            }
            if (oneOrder == 0 || twoOrder == 0)
            {
                if (oneOrder > twoOrder)
                {
                    twoOrder = oneOrder + 1;
                }
                else
                {
                    oneOrder = twoOrder + 1;
                }
            }

            if (oneOrder == twoOrder)
            {
                twoOrder = oneOrder + 1;
            }

            oneEntity.PageOrder = twoOrder;
            twoEntity.PageOrder = oneOrder;


            if (!this.adminPermissionMappingPageData.UpdatePageOrder(oldEntities).GetAwaiter().GetResult())
            {
                throw new ArgumentException("调整页面顺序失败");
            }
        }
    }
}
